package com.coderside.fragment.arithmetic;

import java.nio.Buffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 求N个字符串中的最大公子串
 *思路：
 *	1、从N个字符串中找出最小的字符串
 *	2、分解出最小字符串最大公字符串列表：
 *	例如：abcde
 *	--------------------
 *	abcde
 *	abcd
 *	bcde
 *	abc
 *	bcd
 *	cde
 *	ab
 *	bc
 *	cd
 *	de
 *	----------------------
 *	3、分解出来的公子串从上到下去匹配其他的字符，都能匹配成功则是所要查找的最大公子串
 *	4、如果同时存在两个相等长度的公子串 则以最先发现的为最大
 *
 */
public class MaxPublicStr {

	
	class Combination {

		private CharBuffer a(char[] a, int[] tempNum, int m, int n, int startInd) {
			for (int i = 0; i < n; i++) {
				if (i >= startInd && i < (m + startInd)) {
					tempNum[i] = 1;

				} else {
					tempNum[i] = 0;
				}
			}
			return createResult(a, tempNum, m);
		}

		/**
		 * @param a:组合数组
		 * @param m:生成组合长度
		 * @return :所有连续的组合数组列表
		 */
		public List<CharBuffer> combinationsequence(char[] a, int m) {
			List<CharBuffer> list = new ArrayList<CharBuffer>();
			int n = a.length;
			// 生成辅助数组。首先初始化，将数组前n个元素置1，表示第一个组合为前n个数。
			int[] tempNum = new int[n];
			for (int i = 0; i < tempNum.length; i++) {
				if (i + m > n) {
					break;
				}
				list.add(a(a, tempNum, m, n, i));
			}
			return list;
		}

		// 根据辅助数组和原始数组生成结果数组
		@SuppressWarnings("unchecked")
		public CharBuffer createResult(char[] a, int[] temp, int m) {
			CharBuffer bos = CharBuffer.allocate(m);
			for (int i = 0; i < a.length; i++) {
				if (temp[i] == 1) {
					bos.put(a[i]);
				}
			}
			return bos;
		}

	}

	public List<CharBuffer> combinationsequence(String str, int m) {
		char[] a = str.toCharArray();
		Combination c = new Combination();
		List<CharBuffer> list = c.combinationsequence(a, m);
		return list;
	}

	//字符串列表中的最短字符串
	public String minStr(List<String> strings) {
		return Collections.min(strings, new Comparator<String>() {
			public int compare(String str1, String str2) {
				if (str1.length() < str2.length())
					return -1;
				else if (str1.length() == str2.length())
					return 0;
				else if (str1.length() > str2.length())
					return 1;
				return 0;
			}

		});
	}

	//判断字符串列表中的每个字符串是否包含指定字符串，如果有一个不包含就返回false
	public boolean contains(List<String> strings, String str) {
		for (String s : strings) {
			if (!s.contains(str))
				return false;
		}
		return true;
	}

	public String maxSubString(List<String> strings) {
		String shortStr = minStr(strings);
		int i = shortStr.length();
		//i是1 而不是0 因为当只有一个字符串的时候就没最大可言
		while (i > 1) {
			List<CharBuffer> list = combinationsequence(shortStr, i);
			for (CharBuffer charBuffer : list) {
				Buffer tempstr = charBuffer.rewind();
				if (contains(strings, tempstr.toString())) {
					return tempstr.toString();
				}
			}
			i--;
		}
		return null;
	}

	public static void main(String[] args) {
		MaxPublicStr max = new MaxPublicStr();
		ArrayList<String> strings = new ArrayList<String>(Arrays.asList("ababcdghy", "abcdeftdsfgsdg", "abcdefsdf"));
		String publicStr = max.maxSubString(strings);
		System.out.println(publicStr);

	}
}
